//
// Created by squbirreland on 2021/11/5.
//

#ifndef RLIB_ARRAY_H
#define RLIB_ARRAY_H

#include "../cpp/types.h"
#include "../cpp/interface.h"

/**
 * 动态拓容的数组
 * 每次拓容与删除元素会发生值复制与值迁移
 */
struct Array {
    usize cap;
    usize size;
    usize type_size;
    void *array_p;
};

/**
 * 初始化 根据参数申请内存空间
 * @param init_size 初始化数量 如果为0则内部会修改为1(必须申请空间)
 * @param type_size 类型大小 请务必使用sizeof()
 * @return Array* 返回实例
 */
struct Array *new_array(usize init_size, usize type_size);

/**
 * 构造一个Array 其不通过内存申请构造 而是通过指定内存指针
 * 注意这种方式存在安全隐患
 * 初始的cap与size一致 意为一旦push则会发生值复制以拓容
 * 这么做是为了保护在size外可能的未申请空间
 * @param p 其内部要包含的空间指针 为NULL时返回NULL
 * @param type_size 类型大小 为0时返回NULL
 * @param size 已有的size 为0时返回NULL
 * @return Array*
 */
struct Array *as_array(void *p, usize type_size, usize size);

/**
 * 销毁array 会释放内部的内存空间
 * 如果不想释放内部的空间请直接free(_)
 * @param array 指向该array的指针
 */
void free_array(struct Array *array);

/**
 * 将该数组进行扩容
 * 每次扩容增加一倍长度 并且会将曾经的值复制到新地址 释放旧空间
 * @param array 该结构的指针
 */
void array_expansion(struct Array *array);

/**
 * 将元素推送到数组中
 * 如果元素长度与预设type_size不一致 会发生错乱
 * 如果数组长度不足 会自动发生拓容
 * @param array 该结构的指针
 * @param value 要推送进的元素的指针
 * @return usize 插入后的index
 */
usize array_push(struct Array *array, const void *value);

/**
 * 从数组中pop一个元素 并值复制到新空间返回指针
 * @param array 数组结构的指针
 * @return void* 如果数组为空 返回NULL
 */
void *array_pop(struct Array *array);

/**
 * 获取index下标元素的指针
 * 如果index超出size-1 则返回NULL
 * @param array 当前结构指针
 * @param index 下标
 * @return void* 下标对应的指针
 */
void *array_get(struct Array *array, usize index);

/**
 * 删除对应下标的元素 并将该元素值复制到新空间并返回指针
 * 如果该下标超出返回 返回NULL
 * 元素被删除后 其后方所有元素会往前移复制
 * @param array 当前结构指针
 * @param index 下标
 * @return void* 返回元素的指针
 */
void *array_remove(struct Array *array, usize index);

#endif //RLIB_ARRAY_H
